package common

import (
	"errors"
	"fmt"
	"io"
	"io/ioutil"
	"log"
	"net/http"
	"os"
	"regexp"
	"runtime"
	"strconv"
	"strings"
	"time"

	"github.com/gin-gonic/gin"
)

func FailJson(c *gin.Context, code int, msg string) {
	c.JSON(500, gin.H{
		"code": code,
		"msg":  msg,
	})
}

func GetCacheKey(key string) string {
	return fmt.Sprintf("NT_ORDER_CACHE:%s", key)
}

func WriteLog(ee interface{}) {
	var err error
	if _, ok := ee.(error); ok {
		err = ee.(error)
	} else {
		err = fmt.Errorf("%s", ee)
	}

	if !FileExist("runtime/log") {
		_ = os.MkdirAll("runtime/log", os.ModePerm)
	}

	file, e := os.OpenFile(fmt.Sprintf("runtime/log/error-%s.log", time.Now().Format("2006-01-02")), os.O_RDWR|os.O_APPEND|os.O_CREATE, os.ModePerm)
	if e != nil {
		panic(e)
	}
	var buf [4096]byte
	n := runtime.Stack(buf[:], false)

	log.New(file, "error：", log.Ldate|log.Ltime|log.Llongfile).Println(fmt.Sprintf(" %s ==> %s\n", err.Error(), string(buf[:n])))
}

//
//  Curl 发送http请求
//  @Description: 发送http请求
//  @param method 请求方法
//  @param url
//  @param query 请求参数 支持（string,map[string]string）
//  @param headers 请求头
//  @return []byte
//  @return error
//

var httpClient http.Client
var retry int

func init() {
	httpClient = http.Client{
		Timeout: 10 * time.Second,
	}
	retry = 3
}

func FileExist(path string) bool {
	_, err := os.Lstat(path)
	return !os.IsNotExist(err)
}

func Curl(method, url string, query interface{}, headers map[string]string) ([]byte, error) {
	methodList := map[string]interface{}{"post": nil, "get": nil}
	s := strings.ToLower(method)
	if _, ok := methodList[s]; !ok {
		return nil, errors.New("请求方法必须是post/get")
	}

	data := ""
	if query != nil {
		if params, ok := query.(map[string]string); ok {
			i := 0
			for k, v := range params {
				if i > 0 {
					data += "&"
				}
				data += fmt.Sprintf("%s=%s", k, v)
				i++
			}
		} else {
			data, ok = query.(string)
			if !ok {
				return nil, errors.New("参数类型不合法")
			}
		}
	}

	var post io.Reader
	if method == "GET" {
		if len(data) > 0 {
			if strings.ContainsRune(url, '?') {
				url = url + "&" + data
			} else {
				url = url + "?" + data
			}
		}
	} else {
		post = strings.NewReader(data)
	}
	request, err := http.NewRequest(strings.ToUpper(method), url, post)
	if err != nil {
		return nil, err
	}

	hasUserAgent := false
	if headers != nil {
		for hName, hVal := range headers {
			if strings.ToLower(hName) == "user-agent" {
				hasUserAgent = true
			}
			request.Header.Add(hName, hVal)
		}
	}

	if !hasUserAgent {
		request.Header.Add("Accept-Encoding", "identity")
		request.Header.Add("user-agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/92.0.4515.159 Safari/537.36")
	}

	response, err := httpClient.Do(request)
	if err != nil {
		return nil, err
	}
	defer response.Body.Close()

	if response.StatusCode != 200 {
		if retry > 0 {
			fmt.Printf("第%d次尝试\n", retry)
			retry = retry - 1
			return Curl(method, url, query, headers)
		}
	}

	res, err := ioutil.ReadAll(response.Body)
	if err != nil {
		return nil, err
	}

	return res, nil
}

func SplitMultipleItem(itemId string) []string {
	compile, err := regexp.Compile("[;\\r\\n, ]+")
	if err != nil {
		panic(err)
	}
	res := compile.Split(itemId, -1)
	list := make([]string, 0)
	for _, re := range res {
		space := strings.TrimSpace(re)
		if space != "" {
			list = append(list, space)
		}
	}
	return list
}

func RemoveRepeatedElementAndEmpty(arr []string) []string {
	newArr := make([]string, 0)
	for _, item := range arr {
		if "" == strings.TrimSpace(item) {
			continue
		}

		repeat := false
		if len(newArr) > 0 {
			for _, v := range newArr {
				if v == item {
					repeat = true
					break
				}
			}
		}

		if repeat {
			continue
		}

		newArr = append(newArr, item)
	}
	return newArr
}

func IntVal(i string) int {
	if "" == strings.TrimSpace(i) {
		return 0
	}

	atoi, err := strconv.Atoi(i)
	if err != nil {
		panic(err)
	}
	return atoi
}

func Float64Val(i string, bitSize int) float64 {
	if "" == strings.TrimSpace(i) {
		return 0
	}

	atoi, err := strconv.ParseFloat(i, bitSize)
	if err != nil {
		panic(err)
	}
	return atoi
}

func UFirst(s string) string {
	res := ""
	ss := strings.Split(s, "")
	for i := 0; i < len(ss); i++ {
		if i == 0 {
			res += strings.ToUpper(ss[i])
		} else {
			res += ss[i]
		}
	}
	return res
}

func FillQuestionnaire(num int) string {
	var s string
	for i := 0; i < num; i++ {
		if i > 0 {
			s += ","
		}
		s += "?"
	}
	return s
}
